
package urbanparks;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import exceptions.FileFormatException;

/**
 * Class that parses and stores values read from an external
 * CSV file.
 * 
 * @author Andrew Boguk
 * @version 1
 */
public class ParkSet {
  /** Total parameters in Park class, used for CSV */
  private final static int TOTAL_PARAMETERS = 10;
  /** Map containing Park objects, keys are park name. */
  public final Map<String, Park> my_parks;
  /** File containing Park information. */
  private final File my_file;

  
  /**
   * Construct ParkSet class, assign data file and Map.
   * 
   * @param the_park_file File for the
   */
  public ParkSet(File the_park_file) {
    my_parks = new HashMap<String, Park>();
    my_file = the_park_file;
    loadFromFile();
  }

  /**
   * Populate map with lowercase keys of of park names. Keys
   * are mapped to new Park object, parameters are read from
   * park.csv file.
   * 
   * Parsed lines smaller than required parameters are
   * skipped. Parsed lines larger than required parameters
   * are cut off at TOTAL_PARAMETERS.
   */
  public void loadFromFile() {
    my_parks.clear();
    final Scanner in;
    String[] values;

    try {
      if (my_file != null && !my_file.exists()) {
        my_file.createNewFile();
      } else {
        in = new Scanner(my_file);
        while (in.hasNextLine()) {
          values = in.nextLine().split(",");

          //Skip incorrect formatting.
          if (values.length < TOTAL_PARAMETERS) {
            continue;
          }

          //Trim input.
          for (int i = 0; i < values.length; i++) {
            values[i] = values[i].trim();
          }

          //Create new Park.
          int i = 0;
          my_parks.put(values[i].toLowerCase(), new Park(
              values[i++], values[i++], values[i++],
              values[i++], values[i++], values[i++],
              values[i++], values[i++], values[i++],
              values[i++]));
        }
      }
    } catch (final IOException e) {
      /*
       * Send error to GUI notifying that file cannot be
       * open or read/write permissions missing.
       */
      throw new FileFormatException("Park File");
    }
  }

  /**
   * Get the Park class by park name, returns null if the
   * park doesn't exist.
   * 
   * Input park name is not case-sensitive.
   * 
   * @param the_park_name Park name to search for.
   * @return Park by Park Name, null if doesn't exist.
   */
  public Park getPark(String the_park_name) {
    return my_parks.get(the_park_name.toLowerCase());
  }

  /**
   * @param the_manager Manager email to search for.
   * @return List of parks that contain specified manager.
   */
  public List<Park> getParksManagedBy(String the_manager) {
    final List<Park> temp = new LinkedList<Park>();

    for (Park park : my_parks.values()) {
      if (park.getManagerEmail().equalsIgnoreCase(
          the_manager)) {
        temp.add(park);
      }
    }

    return temp;
  }

  /**
   * @param the_region Region to search by.
   * @return List of parks that are in specified region.
   */
  public List<Park> getParksInRegion(String the_region) {
    final List<Park> temp = new LinkedList<Park>();
    
    for (Park park : my_parks.values()) {
      if (park.getCity().equalsIgnoreCase(the_region)) {
        temp.add(park);
      }
    }
    
    return temp;
  }

  /**
   * @param the_district District to search by.
   * @return List of parks that are in specific district.
   */
  public List<Park> getParksInDistrict(String the_district) {
    final List<Park> temp = new LinkedList<Park>();

    for (Park park : my_parks.values()) {
      if (park.getParkDistrict().equalsIgnoreCase(
          the_district)) {
        temp.add(park);
      }
    }

    return temp;
  }
  
  /**
   * Write to file by clearing CSV text and re-entering
   * each park, information separated by commas and parks
   * separated by system newline character.
   */
  public void writeFile() {
    try {
      FileOutputStream out =
          new FileOutputStream(my_file, false);
      
      for (Park park : my_parks.values())
      {
        out.write((park.getFileString() + System.getProperty("line.separator")).getBytes());
      }
      
      out.close();
    } catch (IOException e) {
      // TODO Problem closing file.
      //e.printStackTrace();
    }
  }
}
